#define __LIBRARY__ 
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <linux/sched.h>
#include <pthread.h>
#include <errno.h>

#define RAND 256
#define N 1024
#define MAXTEST   256
#define MAXTHREAD 64

char mem[N*N];
int Running=0;
int StopControl=0;


int NumTime     =5;
int NumThread   =5;

  int ThreadCount=0;
  int NumCorrect=0;
  int NumError=0;
  int NumFinish=0;
  int NumTotal=N*N;

int TID[MAXTHREAD];
pthread_t thread[MAXTHREAD]= {};
  
  int scoreStatus[MAXTHREAD];
char *AddrStart[MAXTHREAD];
char *AddrEnd  [MAXTHREAD];

  int MemTotal[MAXTHREAD];
  int MemCorrect[MAXTHREAD];
  int MemError[MAXTHREAD];
  int MemFinish[MAXTHREAD];
double       FinishedPrecent[MAXTHREAD];


int test(char *addr)
{
    int i,j,Rand;
    char score[5]= {0x00,0xFF,0x55,0xAA,0x00};
    srand(time(NULL));
    Rand=rand()%RAND;
    score[4]= Rand;
    for (j=0; j<NumTime; j++)
        for (i=0; i<5; i++)
        {
            *addr=score[i];
            if(*addr!=score[i])
            {
                return 0;
            }
        }
    return 1;
}
void *work(void)
{
      char *i;
      int C=ThreadCount++;

    scoreStatus[C]	=1;
    MemTotal[C]	=AddrEnd[C]-AddrStart[C]+1;



    for (i=AddrStart[C]; i<=AddrEnd[C]; i++)
    {
        if(StopControl==1)
        {
            break;
        }

        if (test(i))
        {
            MemCorrect[C]++;
            NumCorrect++;
        }
        else
        {
            MemError  [C]++;
            NumError++;
        }

        MemFinish [C]++;
        NumFinish++;

        FinishedPrecent[C]=(double)MemFinish [C]/MemTotal[C];

    }
    scoreStatus[C]=0;

    pthread_exit(0);
return NULL;
}



void setTimes()
{
    int number;
    scanf("%d",&number);
    if(!Running)
    {


        if(number<=0)
        {
            printf("NumTime>0\n");
        }
        else
        {
            NumTime=number;

            printf("Set Test Times :%d\n",NumTime);
        }

    }
    else
    {

        printf("Test is Running,Invalid Input!\n");
    }

    return;
}
void setThread()
{
    int number;
    scanf("%d",&number);
    if(!Running)
    {


        if(number<=0)
        {
            printf("NumThread>0\n");
        }
        else
        {
            NumThread=number;
            printf("Set Thread Times :%d\n",NumThread);
        }

    }
    else
    {
        printf("Test is Running,Invalid Input!\n");

    }

    return;
}
void go()
{
    int i;
    int length;
    int pc_error;

    if(Running)
    {
        StopControl=1;
        for (i=0; i<NumThread; i++)
            pthread_join(thread[i],NULL);
        StopControl=0;
    }

    ThreadCount=0;
    NumCorrect=0;
    NumError=0;
    NumFinish=0;
    Running=1;
    StopControl=0;
    length=N*N/NumThread;

    memset(AddrStart,0,sizeof(AddrStart));
    memset(AddrEnd,0,sizeof(AddrEnd));
    memset(MemTotal,0,sizeof(MemTotal));
    memset(MemFinish,0,sizeof(MemFinish));
    memset(MemCorrect,0,sizeof(MemCorrect));
    memset(MemError,0,sizeof(MemError));
    memset(FinishedPrecent,0,sizeof(FinishedPrecent));
    memset(scoreStatus,0,sizeof(scoreStatus));


    printf("Test number:%d,Thread number:%d and Test Start...\n",NumTime,NumThread);
    for (i=0; i<NumThread; i++)
    {
        AddrStart[i]    =&mem[i*length];
        AddrEnd [i]     =(i==NumThread-1)?&mem[N*N]-1:&mem[(i+1)*length-1];
        pc_error=pthread_create(&thread[i], NULL, (void  *)work, NULL);
    }
    return;
}
void getStatus()
{
    int i;
    if(Running)
    {

        for (i=0; i<NumThread; i++)
        {
            printf("Thread %2d:",i);
            if(scoreStatus[i]==1)
            {
                printf("Running ");
            }
            else
            {
                printf("Exited  ");
            }
            printf("[%08X-%08X]",(  int)(AddrStart[i]-AddrStart[0]),(  int)(AddrEnd[i]-AddrStart[0]));
            printf(" %d/%d, %.2lf%%",MemFinish[i],MemTotal[i],FinishedPrecent[i]*100);
            printf(" %d Error",MemError[i]);
            printf("\n");
        }
    }
    else
    {
        printf("No Thread Running!\n");
    }
}

void abortThread()
{
    int i;
    if(Running)
    {
        StopControl=1;
        for (i=0; i<NumThread; i++)
            pthread_join(thread[i],NULL);
        getStatus();
        Running=0;
        printf("All Threads Stopped!\n");
    }
    else
    {
        printf("No Thread Running!\n");
    }
    return;
}
void exitProcess()
{
    abortThread();
    return;
}

int main()
{
    char command[100];
    printf("Welcome to KL Memory Test!\n");

    while(1)
    {
printf(">>>");
fflush(stdout);
        scanf("%s",command);

        if(strcmp(command,"times")==0)
        {
            setTimes();
        }
        else if(strcmp(command,"thread")==0)
        {
            setThread();
        }
        else  if(strcmp(command,"go")==0)
        {
            go();
        }
        else  if(strcmp(command,"status")==0)
        {
            getStatus();
        }
        else  if(strcmp(command,"abort")==0)
        {
            abortThread();
        }
        else   if(strcmp(command,"exit")==0)
        {
            abortThread();
            break;
        }
        else
        {
            printf("No Such Command!\n");
        }

    }
    printf("Process Finished!\n");
    return 0;
}

